﻿using Microsoft.SharePoint;
using Microsoft.SharePoint.Publishing.Navigation;
using Microsoft.SharePoint.Taxonomy;
using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using Microsoft.SharePoint.Client;
using System.Security;

namespace Tm_Console
{
    class Program
    {
        static void Main(string[] args)
        {
            int selectedOption = -1;
            bool redo = false;
            do
            {
                redo = false;
                Console.Clear();
                Console.ForegroundColor = ConsoleColor.Cyan;
                Console.WriteLine("TAXONOMY Exporter and Importer for Sharepoint 2013");
                Console.WriteLine("--------------------------------------------------\n");
                Console.ForegroundColor = ConsoleColor.White;
                Console.WriteLine("Select an option:");
                Console.ForegroundColor = ConsoleColor.White;
                Console.WriteLine("1. Backup TermGroup");
                Console.WriteLine("2. Backup TermSet");
                Console.WriteLine("3. Restore TermGroup");
                Console.WriteLine("4. Restore TermSet");
                Console.WriteLine("5. Backup TermGroup (Sharepoint Online)");
                Console.WriteLine("6. Backup TermSet (Sharepoint Online)");
                Console.WriteLine("7. Restore TermGroup (Sharepoint Online)");
                Console.WriteLine("8. Restore TermSet (Sharepoint Online)");
                Console.WriteLine("9. Help");
                Console.WriteLine("0. Menu");
                Console.Write("\nYour Option: ");
                Console.ForegroundColor = ConsoleColor.Gray;

                string response = Console.ReadLine();
                Console.WriteLine();
                try
                {
                    if (int.TryParse(response, out selectedOption))
                    {
                        if (selectedOption == 1)
                        {
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.Write("  Enter Site URL: ");
                            Console.ForegroundColor = ConsoleColor.Gray;
                            string url = Console.ReadLine();
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.Write("  Enter TermGroup Path: ");
                            Console.ForegroundColor = ConsoleColor.Gray;
                            string path = Console.ReadLine();
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.WriteLine();
                            Console.WriteLine("\nPerforming Backup Please Wait....");
                            XElement xEle = TakeTermGroupBackup(url, path);
                            Console.Write("Path to save the file: ");
                            Console.ForegroundColor = ConsoleColor.Gray;
                            string pathToSave = Console.ReadLine();
                            if (pathToSave != string.Empty)
                            {
                                xEle.Save(pathToSave);
                                Console.ForegroundColor = ConsoleColor.White;
                                Console.WriteLine("File Exported Successfully !!!");
                            }
                        }
                        else if (selectedOption == 2)
                        {
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.Write("  Enter Site URL: ");
                            Console.ForegroundColor = ConsoleColor.Gray;
                            string url = Console.ReadLine();
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.Write("  Enter TermSet Path: ");
                            Console.ForegroundColor = ConsoleColor.Gray;
                            string path = Console.ReadLine();
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.WriteLine();
                            Console.WriteLine("\nPerforming Backup Please Wait....");
                            XElement xEle = TakeTermSetBackup(url, path);
                            Console.Write("Path to save the file: ");
                            Console.ForegroundColor = ConsoleColor.Gray;
                            string pathToSave = Console.ReadLine();
                            if (pathToSave != string.Empty)
                            {
                                xEle.Save(pathToSave);
                                Console.ForegroundColor = ConsoleColor.White;
                                Console.WriteLine("File Exported Successfully !!!");
                            }
                        }
                        else if (selectedOption == 3)
                        {
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.Write("  Enter File Path: ");
                            Console.ForegroundColor = ConsoleColor.Gray;
                            string filePath = Console.ReadLine();
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.Write("  Enter Site URL: ");
                            Console.ForegroundColor = ConsoleColor.Gray;
                            string url = Console.ReadLine();
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.Write("  Enter TermStore Path: ");
                            Console.ForegroundColor = ConsoleColor.Gray;
                            string path = Console.ReadLine();
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.WriteLine();
                            Console.WriteLine("Restoring the backup... Please wait");
                            RestoreTermGroup(url, path, filePath);
                            Console.WriteLine("Taxonomy Restored successfully !!!");
                        }
                        else if (selectedOption == 4)
                        {
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.Write("  Enter File Path: ");
                            Console.ForegroundColor = ConsoleColor.Gray;
                            string filePath = Console.ReadLine();
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.Write("  Enter Site URL: ");
                            Console.ForegroundColor = ConsoleColor.Gray;
                            string url = Console.ReadLine();
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.Write("  Enter TermGroup Path: ");
                            Console.ForegroundColor = ConsoleColor.Gray;
                            string path = Console.ReadLine();
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.WriteLine();
                            Console.WriteLine("Restoring the backup... Please wait");
                            RestoreTermSet(url, path, filePath);
                            Console.WriteLine("Taxonomy Restored successfully !!!");
                        }
                        else if (selectedOption == 5)
                        {
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.Write("  Enter Site URL: ");
                            Console.ForegroundColor = ConsoleColor.Gray;
                            string siteURL = Console.ReadLine();
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.Write("  Enter User Name: ");
                            Console.ForegroundColor = ConsoleColor.Gray;
                            string userName = Console.ReadLine();
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.Write("  Enter Password: ");
                            Console.ForegroundColor = ConsoleColor.Gray;
                            string password = Console.ReadLine();
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.Write("  Enter TermGroup Path: ");
                            Console.ForegroundColor = ConsoleColor.Gray;
                            string path = Console.ReadLine();
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.WriteLine();
                            Console.WriteLine("\nPerforming Backup Please Wait....");
                            XElement xEle = TakeTermGroupBackupOnline(siteURL, userName, password, path);
                            Console.Write("Path to save the file: ");
                            Console.ForegroundColor = ConsoleColor.Gray;
                            string pathToSave = Console.ReadLine();
                            if (pathToSave != string.Empty)
                            {
                                xEle.Save(pathToSave);
                                Console.ForegroundColor = ConsoleColor.White;
                                Console.WriteLine("File Exported Successfully !!!");
                            }
                        }
                        else if (selectedOption == 6)
                        {
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.Write("  Enter Site URL: ");
                            Console.ForegroundColor = ConsoleColor.Gray;
                            string siteURL = Console.ReadLine();
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.Write("  Enter User Name: ");
                            Console.ForegroundColor = ConsoleColor.Gray;
                            string userName = Console.ReadLine();
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.Write("  Enter Password: ");
                            Console.ForegroundColor = ConsoleColor.Gray;
                            string password = Console.ReadLine();
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.Write("  Enter TermSet Path: ");
                            Console.ForegroundColor = ConsoleColor.Gray;
                            string path = Console.ReadLine();
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.WriteLine();
                            Console.WriteLine("\nPerforming Backup Please Wait....");
                            XElement xEle = TakeTermSetBackupOnline(siteURL, userName, password, path);
                            Console.Write("Path to save the file: ");
                            Console.ForegroundColor = ConsoleColor.Gray;
                            string pathToSave = Console.ReadLine();
                            if (pathToSave != string.Empty)
                            {
                                xEle.Save(pathToSave);
                                Console.ForegroundColor = ConsoleColor.White;
                                Console.WriteLine("File Exported Successfully !!!");
                            }
                        }
                        else if (selectedOption == 7)
                        {
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.Write("  Enter File Path: ");
                            Console.ForegroundColor = ConsoleColor.Gray;
                            string filePath = Console.ReadLine();
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.Write("  Enter Site URL: ");
                            Console.ForegroundColor = ConsoleColor.Gray;
                            string url = Console.ReadLine();
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.Write("  Enter User Name: ");
                            Console.ForegroundColor = ConsoleColor.Gray;
                            string userName = Console.ReadLine();
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.Write("  Enter Password: ");
                            Console.ForegroundColor = ConsoleColor.Gray;
                            string password = Console.ReadLine();
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.Write("  Enter TermStore Path: ");
                            Console.ForegroundColor = ConsoleColor.Gray;
                            string path = Console.ReadLine();
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.WriteLine();
                            Console.WriteLine("Restoring the backup... Please wait");
                            RestoreTermGroupOnline(url, userName, password, path, filePath);
                            Console.WriteLine("Taxonomy Restored successfully !!!");
                        }
                        else if (selectedOption == 8)
                        {
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.Write("  Enter File Path: ");
                            Console.ForegroundColor = ConsoleColor.Gray;
                            string filePath = Console.ReadLine();
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.Write("  Enter Site URL: ");
                            Console.ForegroundColor = ConsoleColor.Gray;
                            string url = Console.ReadLine();
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.Write("  Enter User Name: ");
                            Console.ForegroundColor = ConsoleColor.Gray;
                            string userName = Console.ReadLine();
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.Write("  Enter Password: ");
                            Console.ForegroundColor = ConsoleColor.Gray;
                            string password = Console.ReadLine();
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.Write("  Enter TermSet Path: ");
                            Console.ForegroundColor = ConsoleColor.Gray;
                            string path = Console.ReadLine();
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.WriteLine();
                            Console.WriteLine("Restoring the backup... Please wait");
                            RestoreTermSetOnline(url, userName, password, path, filePath);
                            Console.WriteLine("Taxonomy Restored successfully !!!");
                        }
                        else if (selectedOption == 9)
                        {
                            string helpText = GetHelp();
                            Console.WriteLine(helpText);
                        }
                        else if (selectedOption == 0)
                        {
                            redo = true;
                            goto SKIPINPUT;
                        }
                    }
                    else
                        Console.WriteLine("Invalid Option Selected.");
                }
                catch (Exception ee)
                {
                    Console.WriteLine("\nError: " + ee.Message + "\nNote: Make sure you're the Termstore administrator");
                }
                Console.WriteLine();
                Console.ForegroundColor = ConsoleColor.White;
                Console.Write("Do you want to perform more operations [Y] Yes or [N] No:    ");
                string uinput = Console.ReadLine();
                if (uinput == "Y" || uinput == "y")
                    redo = true;
                else
                    redo = false;

            SKIPINPUT:
                Console.WriteLine();
            } while (redo);
        }

        static string GetHelp()
        {
            StringBuilder str = new StringBuilder();
            str.Append("1. The Path\n");
            str.Append("\t The path to the group or the termset is always kind of an xPath expression with forward slashes.\n ");
            str.Append("\t e.g.  <TermStoreName>/<GroupName>/<TermSetName>");
            return str.ToString();
        }

        static void RestoreTermSet(string siteURL, string path, string filePath)
        {
            XElement xTermSetData = XElement.Load(filePath, LoadOptions.None);
            using (SPSite site = new SPSite(siteURL))
            {
                using (SPWeb web = site.OpenWeb())
                {
                    TaxonomySession session = new TaxonomySession(site);
                    string[] termSetData = path.Split('/');
                    string serviceName = termSetData[0];
                    string groupName = termSetData[1];
                    Microsoft.SharePoint.Taxonomy.Group termGroup = session.TermStores[serviceName].Groups[groupName];
                    WriteTermSet(xTermSetData, termGroup.CreateTermSet(xTermSetData.Attribute("Name").Value));
                    session.TermStores[serviceName].CommitAll();
                }
            }
        }

        static void RestoreTermGroup(string siteURL, string path, string filePath)
        {
            XElement xTermGroupData = XElement.Load(filePath, LoadOptions.None);
            using (SPSite site = new SPSite(siteURL))
            {
                using (SPWeb web = site.OpenWeb())
                {
                    TaxonomySession session = new TaxonomySession(site);
                    string[] termSetData = path.Split('/');
                    string serviceName = termSetData[0];
                    TermStore termStore = session.TermStores[serviceName];
                    Microsoft.SharePoint.Taxonomy.Group rootTermGroup = null;

                    rootTermGroup = termStore.CreateGroup(xTermGroupData.Attribute("Name").Value);
                    XElement[] termSets = xTermGroupData.Elements("TermSet").ToArray();
                    for (int g = 0; g < termSets.Count(); g++)
                    {
                        WriteTermSet(termSets[g], rootTermGroup.CreateTermSet(termSets[g].Attribute("Name").Value));
                    }
                    termStore.CommitAll();
                }
            }
        }

        static void WriteTermSet(XElement xTermSetData, TermSet termSet)
        {
            termSet.IsAvailableForTagging = bool.Parse(xTermSetData.Attribute("Tagging").Value);
            //setting term order
            if (xTermSetData.Element("TermSortOrder") != null)
            {
                termSet.CustomSortOrder = string.Join(":", (from b in xTermSetData.Element("TermSortOrder").Elements("ID")
                                                            select b.Value));
            }
            //filling shared properties
            if (xTermSetData.Element("SharedProperties") != null)
            {
                XElement[] properties = xTermSetData.Element("SharedProperties").Elements("Property").ToArray();
                for (int u = 0; u < properties.Count(); u++)
                {
                    termSet.SetCustomProperty(properties[u].Attribute("Key").Value, properties[u].Attribute("Value").Value);
                }
            }
            if (xTermSetData.Elements("Terms").Count() !=0)
            {
                XElement[] termEles = xTermSetData.Element("Terms").Elements("Term").ToArray();

                for (int i = 0; i < xTermSetData.Element("Terms").Elements("Term").Count(); i++)
                {
                    Term term = termSet.CreateTerm(termEles[i].Attribute("Name").Value, CultureInfo.CurrentCulture.LCID);
                    term.IsAvailableForTagging = bool.Parse(termEles[i].Attribute("Tagging").Value);
                    term.SetDescription(termEles[i].Attribute("Description").Value, CultureInfo.CurrentCulture.LCID);

                    //filling local properties
                    if (termEles[i].Element("LocalProperties") != null)
                    {
                        XElement[] properties = termEles[i].Element("LocalProperties").Elements("Property").ToArray();
                        for (int u = 0; u < properties.Count(); u++)
                        {
                            term.SetLocalCustomProperty(properties[u].Attribute("Key").Value, properties[u].Attribute("Value").Value);
                        }
                    }

                    //filling shared properties
                    if (termEles[i].Element("SharedProperties") != null)
                    {
                        XElement[] properties = termEles[i].Element("SharedProperties").Elements("Property").ToArray();
                        for (int u = 0; u < properties.Count(); u++)
                        {
                            term.SetCustomProperty(properties[u].Attribute("Key").Value, properties[u].Attribute("Value").Value);
                        }
                    }
                    if (xTermSetData.Element("Terms").Elements("Term").ToArray()[i] != null)
                        CreateTermData(xTermSetData.Element("Terms").Elements("Term").ToArray()[i], term);
                }
            }
        }

        static void WriteTermSetOnline(XElement xTermSetData, Microsoft.SharePoint.Client.Taxonomy.TermSet termSet)
        {
            termSet.IsAvailableForTagging = bool.Parse(xTermSetData.Attribute("Tagging").Value);
            //setting term order
            if (xTermSetData.Element("TermSortOrder") != null)
            {
                termSet.CustomSortOrder = string.Join(":", (from b in xTermSetData.Element("TermSortOrder").Elements("ID")
                                                            select b.Value));
            }
            //filling shared properties
            if (xTermSetData.Element("SharedProperties") != null)
            {
                XElement[] properties = xTermSetData.Element("SharedProperties").Elements("Property").ToArray();
                for (int u = 0; u < properties.Count(); u++)
                {
                    termSet.SetCustomProperty(properties[u].Attribute("Key").Value, properties[u].Attribute("Value").Value);
                }
            }
            if (xTermSetData.Elements("Terms").Count() != 0)
            {
                XElement[] termEles = xTermSetData.Element("Terms").Elements("Term").ToArray();

                for (int i = 0; i < xTermSetData.Element("Terms").Elements("Term").Count(); i++)
                {
                    Microsoft.SharePoint.Client.Taxonomy.Term term = termSet.CreateTerm(termEles[i].Attribute("Name").Value, CultureInfo.CurrentCulture.LCID, Guid.NewGuid());
                    term.IsAvailableForTagging = bool.Parse(termEles[i].Attribute("Tagging").Value);
                    term.SetDescription(termEles[i].Attribute("Description").Value, CultureInfo.CurrentCulture.LCID);

                    //filling local properties
                    if (termEles[i].Element("LocalProperties") != null)
                    {
                        XElement[] properties = termEles[i].Element("LocalProperties").Elements("Property").ToArray();
                        for (int u = 0; u < properties.Count(); u++)
                        {
                            term.SetLocalCustomProperty(properties[u].Attribute("Key").Value, properties[u].Attribute("Value").Value);
                        }
                    }

                    //filling shared properties
                    if (termEles[i].Element("SharedProperties") != null)
                    {
                        XElement[] properties = termEles[i].Element("SharedProperties").Elements("Property").ToArray();
                        for (int u = 0; u < properties.Count(); u++)
                        {
                            term.SetCustomProperty(properties[u].Attribute("Key").Value, properties[u].Attribute("Value").Value);
                        }
                    }
                    if (xTermSetData.Element("Terms").Elements("Term").ToArray()[i] != null)
                        CreateTermDataOnline(xTermSetData.Element("Terms").Elements("Term").ToArray()[i], term);
                }
            }
        }

        static XElement TakeTermGroupBackup(string siteURL, string path)
        {
            XElement xTermGroup = new XElement("TermGroup");

            using (SPSite site = new SPSite(siteURL))
            {
                using (SPWeb web = site.OpenWeb())
                {
                    TaxonomySession session = new TaxonomySession(site);
                    string[] termSetData = path.Split('/');
                    string serviceName = termSetData[0];
                    string groupName = termSetData[1];

                    string[] terms = new string[termSetData.Length - 2];
                    Array.Copy(termSetData, 2, terms, 0, terms.Length);
                    xTermGroup.Add(new XAttribute("Name", groupName));

                    Microsoft.SharePoint.Taxonomy.Group termGroup = session.TermStores[serviceName].Groups[groupName];
                    for (int l = 0; l < termGroup.TermSets.Count; l++)
                    {
                        xTermGroup.Add(GetTermSetData(termGroup.TermSets[l]));
                    }
                }
            }
            return xTermGroup;
        }

        static XElement GetTermSetData(TermSet termSet)
        {
            XElement xEle = new XElement("TermSet");
            TermSet backupTermSet = termSet;
            xEle.Add(new XAttribute("Name", backupTermSet.Name), new XAttribute("Tagging", (backupTermSet.IsAvailableForTagging) ? true : false));

            //getting the custom sortorder
            if (backupTermSet.CustomSortOrder != null)
            {
                string[] termIDs = backupTermSet.CustomSortOrder.Split(':');
                XElement sortElements = new XElement("TermSortOrder");
                for (int i = 0; i < termIDs.Length; i++)
                {
                    sortElements.Add(new XElement("ID", termIDs[i]));
                }
                xEle.Add(sortElements);
            }

            //getting custom Properties
            if (backupTermSet.CustomProperties.Count > 0)
            {
                XElement xCustomProp = new XElement("CustomProperties");
                for (int j = 0; j < backupTermSet.CustomProperties.Keys.Count; j++)
                {
                    xCustomProp.Add(new XElement("Property", new XAttribute("Key", backupTermSet.CustomProperties.Keys.ToArray()[j]), new XAttribute("Value", backupTermSet.CustomProperties[backupTermSet.CustomProperties.Keys.ToArray()[j]])));
                }
                xEle.Add(xCustomProp);
            }

            //getting all the terms
            TermCollection allSubTerms = backupTermSet.Terms;

            if (allSubTerms.Count > 0)
            {
                XElement termCollection = new XElement("Terms");
                foreach (Term t in allSubTerms)
                {
                    termCollection.Add(GetTermsData(t));
                }
                xEle.Add(termCollection);
            }
            return xEle;
        }

        static XElement TakeTermSetBackup(string siteURL, string path)
        {
            using (SPSite site = new SPSite(siteURL))
            {
                using (SPWeb web = site.OpenWeb())
                {
                    TaxonomySession session = new TaxonomySession(site);
                    string[] termSetData = path.Split('/');
                    string serviceName = termSetData[0];
                    string groupName = termSetData[1];
                    string termSet = termSetData[2];

                    string[] terms = new string[termSetData.Length - 3];
                    Array.Copy(termSetData, 3, terms, 0, terms.Length);
                    return GetTermSetData(session.TermStores[serviceName].Groups[groupName].TermSets[termSet]);
                }
            }
        }

        static XElement GetTermsDataOnline(Microsoft.SharePoint.Client.Taxonomy.Term termObject)
        {
            XElement term = new XElement("Term");
            if (termObject.Terms.Count > 0)
            {
                for (int i = 0; i < termObject.Terms.Count; i++)
                {
                    term.Add(GetTermsDataOnline(termObject.Terms[i]));
                }
            }

            term.Add(
                    new XAttribute("Name", termObject.Name),
                    new XAttribute("Tagging", (termObject.IsAvailableForTagging) ? "true" : "false"),
                   new XAttribute("Description", termObject.Description)
                    );

            //getting local shared properties
            if (termObject.CustomProperties.Count > 0)
            {
                XElement xCustomProp = new XElement("SharedProperties");
                for (int j = 0; j < termObject.CustomProperties.Keys.Count; j++)
                {
                    xCustomProp.Add(new XElement("Property", new XAttribute("Key", termObject.CustomProperties.Keys.ToArray()[j]), new XAttribute("Value", termObject.CustomProperties[termObject.CustomProperties.Keys.ToArray()[j]])));
                }
                term.Add(xCustomProp);
            }

            //getting local custom properties
            if (termObject.LocalCustomProperties.Count > 0)
            {
                XElement xCustomProp = new XElement("LocalProperties");
                for (int k = 0; k < termObject.LocalCustomProperties.Keys.Count; k++)
                {
                    xCustomProp.Add(new XElement("Property", new XAttribute("Key", termObject.LocalCustomProperties.Keys.ToArray()[k]), new XAttribute("Value", termObject.LocalCustomProperties[termObject.LocalCustomProperties.Keys.ToArray()[k]])));
                }
                term.Add(xCustomProp);
            }

            //getting the custom sortorder
            XElement sortElements = new XElement("TermSortOrder");
            if (termObject.CustomSortOrder != null)
            {
                string[] termIDs = termObject.CustomSortOrder.Split(':');
                for (int i = 0; i < termIDs.Length; i++)
                {
                    sortElements.Add(new XElement("ID", termIDs[i]));
                }
                term.Add(sortElements);
            }
            return term;
        }

        static XElement GetTermsData(Term termObject)
        {
            XElement term = new XElement("Term");
            if (termObject.Terms.Count > 0)
            {
                for (int i = 0; i < termObject.Terms.Count; i++)
                {
                    term.Add(GetTermsData(termObject.Terms[i]));
                }
            }

            term.Add(
                    new XAttribute("Name", termObject.Name),
                    new XAttribute("Tagging", (termObject.IsAvailableForTagging) ? "true" : "false"),
                    new XAttribute("Description", termObject.GetDescription())
                    );

            //getting local shared properties
            if (termObject.CustomProperties.Count > 0)
            {
                XElement xCustomProp = new XElement("SharedProperties");
                for (int j = 0; j < termObject.CustomProperties.Keys.Count; j++)
                {
                    xCustomProp.Add(new XElement("Property", new XAttribute("Key", termObject.CustomProperties.Keys.ToArray()[j]), new XAttribute("Value", termObject.CustomProperties[termObject.CustomProperties.Keys.ToArray()[j]])));
                }
                term.Add(xCustomProp);
            }

            //getting local custom properties
            if (termObject.LocalCustomProperties.Count > 0)
            {
                XElement xCustomProp = new XElement("LocalProperties");
                for (int k = 0; k < termObject.LocalCustomProperties.Keys.Count; k++)
                {
                    xCustomProp.Add(new XElement("Property", new XAttribute("Key", termObject.LocalCustomProperties.Keys.ToArray()[k]), new XAttribute("Value", termObject.LocalCustomProperties[termObject.LocalCustomProperties.Keys.ToArray()[k]])));
                }
                term.Add(xCustomProp);
            }

            //getting the custom sortorder
            XElement sortElements = new XElement("TermSortOrder");
            if (termObject.CustomSortOrder != null)
            {
                string[] termIDs = termObject.CustomSortOrder.Split(':');
                for (int i = 0; i < termIDs.Length; i++)
                {
                    sortElements.Add(new XElement("ID", termIDs[i]));
                }
                term.Add(sortElements);
            }
            return term;
        }

        static void CreateTermData(XElement termNode, Term term)
        {
            if (termNode.Element("Term") != null)
            {
                XElement[] termNodes = termNode.Elements("Term").ToArray();
                for (int i = 0; i < termNode.Elements("Term").Count(); i++)
                {
                    Term t = term.CreateTerm(termNodes[i].Attribute("Name").Value, CultureInfo.CurrentCulture.LCID);
                    t.IsAvailableForTagging = bool.Parse(termNodes[i].Attribute("Tagging").Value);
                    t.SetDescription(termNodes[i].Attribute("Description").Value, CultureInfo.CurrentCulture.LCID);

                    //filling local properties
                    if (termNodes[i].Element("LocalProperties") != null)
                    {
                        XElement[] properties = termNodes[i].Element("LocalProperties").Elements("Property").ToArray();
                        for (int u = 0; u < properties.Count(); u++)
                        {
                            t.SetLocalCustomProperty(properties[u].Attribute("Key").Value, properties[u].Attribute("Value").Value);
                        }
                    }

                    //filling shared properties
                    if (termNodes[i].Element("SharedProperties") != null)
                    {
                        XElement[] properties = termNodes[i].Element("SharedProperties").Elements("Property").ToArray();
                        for (int u = 0; u < properties.Count(); u++)
                        {
                            t.SetCustomProperty(properties[u].Attribute("Key").Value, properties[u].Attribute("Value").Value);
                        }
                    }
                    CreateTermData(termNode.Elements("Term").ToArray()[i], t);
                }
            }
        }

        static void CreateTermDataOnline(XElement termNode, Microsoft.SharePoint.Client.Taxonomy.Term term)
        {
            if (termNode.Element("Term") != null)
            {
                XElement[] termNodes = termNode.Elements("Term").ToArray();
                for (int i = 0; i < termNode.Elements("Term").Count(); i++)
                {
                    Microsoft.SharePoint.Client.Taxonomy.Term t = term.CreateTerm(termNodes[i].Attribute("Name").Value, CultureInfo.CurrentCulture.LCID, Guid.NewGuid());
                    t.IsAvailableForTagging = bool.Parse(termNodes[i].Attribute("Tagging").Value);
                    t.SetDescription(termNodes[i].Attribute("Description").Value, CultureInfo.CurrentCulture.LCID);

                    //filling local properties
                    if (termNodes[i].Element("LocalProperties") != null)
                    {
                        XElement[] properties = termNodes[i].Element("LocalProperties").Elements("Property").ToArray();
                        for (int u = 0; u < properties.Count(); u++)
                        {
                            t.SetLocalCustomProperty(properties[u].Attribute("Key").Value, properties[u].Attribute("Value").Value);
                        }
                    }

                    //filling shared properties
                    if (termNodes[i].Element("SharedProperties") != null)
                    {
                        XElement[] properties = termNodes[i].Element("SharedProperties").Elements("Property").ToArray();
                        for (int u = 0; u < properties.Count(); u++)
                        {
                            t.SetCustomProperty(properties[u].Attribute("Key").Value, properties[u].Attribute("Value").Value);
                        }
                    }
                    CreateTermDataOnline(termNode.Elements("Term").ToArray()[i], t);
                }
            }
        }

        static XElement GetTermSetDataOnline(Microsoft.SharePoint.Client.Taxonomy.TermSet termSetObject)
        {
            XElement xEle = new XElement("TermSet");
            xEle.Add(new XAttribute("Name", termSetObject.Name), new XAttribute("Tagging", (termSetObject.IsAvailableForTagging) ? true : false));

            //getting the custom sortorder
            if (termSetObject.CustomSortOrder != null)
            {
                string[] termIDs = termSetObject.CustomSortOrder.Split(':');
                XElement sortElements = new XElement("TermSortOrder");
                for (int i = 0; i < termIDs.Length; i++)
                {
                    sortElements.Add(new XElement("ID", termIDs[i]));
                }
                xEle.Add(sortElements);
            }

            //getting custom Properties
            if (termSetObject.CustomProperties.Count > 0)
            {
                XElement xCustomProp = new XElement("CustomProperties");
                for (int j = 0; j < termSetObject.CustomProperties.Keys.Count; j++)
                {
                    xCustomProp.Add(new XElement("Property", new XAttribute("Key", termSetObject.CustomProperties.Keys.ToArray()[j]), new XAttribute("Value", termSetObject.CustomProperties[termSetObject.CustomProperties.Keys.ToArray()[j]])));
                }
                xEle.Add(xCustomProp);
            }

            //getting all the terms
            Microsoft.SharePoint.Client.Taxonomy.TermCollection allSubTerms = termSetObject.Terms;

            if (allSubTerms.Count > 0)
            {
                XElement termCollection = new XElement("Terms");
                foreach (Microsoft.SharePoint.Client.Taxonomy.Term t in allSubTerms)
                {
                    termCollection.Add(GetTermsDataOnline(t));
                }
                xEle.Add(termCollection);
            }
            return xEle;
        }

        static XElement TakeTermSetBackupOnline(string siteURL, string userName, string password, string path)
        {
            using (ClientContext clientContext = new ClientContext("https://thatthatguy.sharepoint.com/"))
            {
                string passd = "synth@123";
                SecureString passWord = new SecureString();
                foreach (char c in passd)
                {
                    passWord.AppendChar(c);
                }
                clientContext.Credentials = new SharePointOnlineCredentials("ttg@thatthatguy.onmicrosoft.com", passWord);
                Web web = clientContext.Web;
                clientContext.Load(web);
                clientContext.ExecuteQuery();
                Console.WriteLine(web.Title);
                Microsoft.SharePoint.Client.Taxonomy.TaxonomySession taxSession = Microsoft.SharePoint.Client.Taxonomy.TaxonomySession.GetTaxonomySession(clientContext);
                clientContext.Load(taxSession,
                        ts => ts.TermStores.Include(
                            store => store.Name,
                            store => store.Groups.Include(
                                group => group.Name, group => group.TermSets.Include(
                            termSet => termSet.Name, termSet => termSet.Description, termSet => termSet.IsAvailableForTagging, termSet => termSet.Terms, termSet => termSet.CustomProperties, termSet => termSet.CustomSortOrder,
                            termSet => termSet.Terms.Include(
                                term => term.Name, term => term.IsAvailableForTagging, term => term.LocalCustomProperties, term => term.CustomProperties, term => term.Terms, term => term.Description)
                            ))
                          ));
                clientContext.ExecuteQuery();

                if (taxSession != null)
                {
                    Microsoft.SharePoint.Client.Taxonomy.TermStore termStore = taxSession.TermStores[0];
                    string[] termSetData = path.Split('/');
                    string serviceName = termSetData[0];
                    string groupName = termSetData[1];
                    string termSet = termSetData[2];

                    string[] terms = new string[termSetData.Length - 3];
                    Array.Copy(termSetData, 3, terms, 0, terms.Length);

                    Microsoft.SharePoint.Client.Taxonomy.TermGroup termGroup = null;

                    foreach (Microsoft.SharePoint.Client.Taxonomy.TermGroup grp in termStore.Groups)
                    {
                        if (grp.Name == groupName)
                        {
                            termGroup = grp;
                            break;
                        }
                    }

                    Microsoft.SharePoint.Client.Taxonomy.TermSet tSet = null;
                    foreach (Microsoft.SharePoint.Client.Taxonomy.TermSet set in termGroup.TermSets)
                    {
                        if (set.Name == termSet)
                        {
                            tSet = set;
                            break;
                        }
                    }
                    return GetTermSetDataOnline(tSet);
                }
            }
            return null;
        }

        static XElement TakeTermGroupBackupOnline(string siteURL, string userName, string password, string path)
        {
            XElement xTermGroup = new XElement("TermGroup");
            using (ClientContext clientContext = new ClientContext("https://thatthatguy.sharepoint.com/"))
            {
                string passd = "synth@123";
                SecureString passWord = new SecureString();
                foreach (char c in passd)
                {
                    passWord.AppendChar(c);
                }
                clientContext.Credentials = new SharePointOnlineCredentials("ttg@thatthatguy.onmicrosoft.com", passWord);
                Web web = clientContext.Web;
                clientContext.Load(web);
                clientContext.ExecuteQuery();
                Console.WriteLine(web.Title);
                Microsoft.SharePoint.Client.Taxonomy.TaxonomySession taxSession = Microsoft.SharePoint.Client.Taxonomy.TaxonomySession.GetTaxonomySession(clientContext);
                clientContext.Load(taxSession,
                        ts => ts.TermStores.Include(
                            store => store.Name,
                            store => store.Groups.Include(
                                group => group.Name, group => group.TermSets.Include(
                            termSet => termSet.Name, termSet => termSet.Description, termSet => termSet.IsAvailableForTagging, termSet => termSet.Terms, termSet => termSet.CustomProperties, termSet => termSet.CustomSortOrder,
                            termSet => termSet.Terms.Include(
                                term => term.Name, term => term.IsAvailableForTagging, term => term.LocalCustomProperties, term => term.CustomProperties, term => term.Terms, term => term.Description)
                            ))
                          ));
                clientContext.ExecuteQuery();

                if (taxSession != null)
                {
                    Microsoft.SharePoint.Client.Taxonomy.TermStore termStore = taxSession.TermStores[0];
                    string[] termSetData = path.Split('/');
                    string serviceName = termSetData[0];
                    string groupName = termSetData[1];

                    string[] terms = new string[termSetData.Length - 2];
                    Array.Copy(termSetData, 2, terms, 0, terms.Length);
                    xTermGroup.Add(new XAttribute("Name", groupName));

                    Microsoft.SharePoint.Client.Taxonomy.TermGroup termGroup = null;
                    Microsoft.SharePoint.Client.Taxonomy.TermGroupCollection collection = termStore.Groups;

                    foreach (Microsoft.SharePoint.Client.Taxonomy.TermGroup grp in collection)
                    {
                        if (grp.Name == groupName)
                        {
                            termGroup = grp;
                            break;
                        }
                    }

                    for (int l = 0; l < termGroup.TermSets.Count; l++)
                    {
                        xTermGroup.Add(GetTermSetDataOnline(termGroup.TermSets[l]));
                    }
                }
            }
            return xTermGroup;
        }

        static void RestoreTermSetOnline(string siteURL, string userName, string password, string path, string filePath)
        {
            using (ClientContext clientContext = new ClientContext("https://thatthatguy.sharepoint.com/"))
            {
                string passd = "synth@123";
                SecureString passWord = new SecureString();
                foreach (char c in passd)
                {
                    passWord.AppendChar(c);
                }
                clientContext.Credentials = new SharePointOnlineCredentials("ttg@thatthatguy.onmicrosoft.com", passWord);
                Web web = clientContext.Web;
                clientContext.Load(web);
                clientContext.ExecuteQuery();

                Microsoft.SharePoint.Client.Taxonomy.TaxonomySession taxSession = Microsoft.SharePoint.Client.Taxonomy.TaxonomySession.GetTaxonomySession(clientContext);
                XElement xTermSetData = XElement.Load(filePath, LoadOptions.None);
                string[] termSetData = path.Split('/');
                string serviceName = termSetData[0];
                string groupName = termSetData[1];

                Microsoft.SharePoint.Client.Taxonomy.TermGroup termGroup = null;
                Microsoft.SharePoint.Client.Taxonomy.TermGroupCollection collection = taxSession.TermStores[0].Groups;

                foreach (Microsoft.SharePoint.Client.Taxonomy.TermGroup grp in collection)
                {
                    if (grp.Name == groupName)
                    {
                        termGroup = grp;
                        break;
                    }
                }
                WriteTermSetOnline(xTermSetData, termGroup.CreateTermSet(xTermSetData.Attribute("Name").Value, Guid.NewGuid(), CultureInfo.CurrentCulture.LCID));
                taxSession.TermStores[0].CommitAll();

            }

        }

        static void RestoreTermGroupOnline(string siteURL, string userName, string password, string path, string filePath)
        {
            using (ClientContext clientContext = new ClientContext("https://thatthatguy.sharepoint.com/"))
            {
                string passd = "synth@123";
                SecureString passWord = new SecureString();
                foreach (char c in passd)
                {
                    passWord.AppendChar(c);
                }
                clientContext.Credentials = new SharePointOnlineCredentials("ttg@thatthatguy.onmicrosoft.com", passWord);
                Web web = clientContext.Web;
                clientContext.Load(web);
                clientContext.ExecuteQuery();

                Microsoft.SharePoint.Client.Taxonomy.TaxonomySession taxSession = Microsoft.SharePoint.Client.Taxonomy.TaxonomySession.GetTaxonomySession(clientContext);
                XElement xTermSetData = XElement.Load(filePath, LoadOptions.None);
                string[] termSetData = path.Split('/');
                string serviceName = termSetData[0];

                XElement xTermGroupData = XElement.Load(filePath, LoadOptions.None);
                clientContext.Load(taxSession,
                        ts => ts.TermStores.Include(
                            store => store.Name,
                            store => store.Groups.Include(
                                group => group.Name, group => group.TermSets.Include(
                            termSet => termSet.Name, termSet => termSet.Description, termSet => termSet.IsAvailableForTagging, termSet => termSet.Terms, termSet => termSet.CustomProperties, termSet => termSet.CustomSortOrder,
                            termSet => termSet.Terms.Include(
                                term => term.Name, term => term.IsAvailableForTagging, term => term.LocalCustomProperties, term => term.CustomProperties, term => term.Terms, term => term.Description)
                            ))
                          ));

                clientContext.ExecuteQuery();

                Microsoft.SharePoint.Client.Taxonomy.TermStore termStore = taxSession.TermStores[0];
                Microsoft.SharePoint.Client.Taxonomy.TermGroup termGroup = termStore.CreateGroup(xTermGroupData.Attribute("Name").Value, Guid.NewGuid());

                XElement[] termSets = xTermGroupData.Elements("TermSet").ToArray();
                for (int g = 0; g < termSets.Count(); g++)
                {
                    WriteTermSetOnline(termSets[g], termGroup.CreateTermSet(termSets[g].Attribute("Name").Value, Guid.NewGuid(), CultureInfo.CurrentCulture.LCID));
                }
                taxSession.TermStores[0].CommitAll();
            }
        }
    }
}
